//`define TEST_FIRST
module bte_checker(
input clk,
input rst_n, 
output reg   	 busy,
output reg   	 bte_start,
output reg [31:0] tile_x,
output reg [31:0] tile_y,                             
output reg [47:0] vertex0_x               ,
output reg [47:0] vertex0_y               ,
output reg [47:0] vertex1_x               ,
output reg [47:0] vertex1_y               ,  
output reg [47:0] vertex2_x               ,
output reg [47:0] vertex2_y               ,
output reg test_end,
input [31:0]					x_out,
input [31:0]					y_out,
input  						xy_out_en,
input [95:0]      ee0,
input [95:0]      ee1,
input [95:0]      ee2, 
input bte_busy
        );

logic [47:0] v0x;
logic [47:0] v0y; 
logic [47:0] v1x;
logic [47:0] v1y;
logic [47:0] v2x;
logic [47:0] v2y;
logic [63:0] area;


logic [31:0] cur_tile_x;
logic [31:0] cur_tile_y;
logic [47:0] x0;
logic [47:0] y0;
logic [47:0] x1;
logic [47:0] y1;  
logic [47:0] x2;
logic [47:0] y2; 
logic [47:0] a0;
logic [47:0] b0;
logic [47:0] a1;
logic [47:0] b1;  
logic [47:0] a2;
logic [47:0] b2; 
logic [95:0] ee0_int;
logic [95:0] ee1_int; 
logic [95:0] ee2_int; 
logic judge_t0;
logic judge_t1; 
logic judge_t2;
logic [3:0] x_temp;
logic [3:0] y_temp;
logic [95:0] cur_ee0;
logic [95:0] cur_ee1; 
logic [95:0] cur_ee2;
logic [31:0] cur_x;
logic [31:0] cur_y;



reg [63:0] tile_cor_buffer [63:0];
reg [287:0] vertex_buffer [1023:0];
reg [351:0] pixel_buffer [20000000:0];

reg [31:0] vertex_count;
reg [31:0] tile_count;

reg error;
reg [31:0] pixel_in_counter;

wire [351:0] data_true = pixel_buffer[pixel_in_counter];
 

always@(posedge clk or negedge rst_n)
    begin
       if(~rst_n)
        begin
           error <= 0;
           pixel_in_counter <= 0;

        end
       else if(xy_out_en)
        begin
            if(data_true != {ee2,ee1,ee0,y_out,x_out})
                begin
                    error <= 1;
                    $display("error pixel : %d \n",pixel_in_counter);
                end
            else
                error <= 0;
            pixel_in_counter <= pixel_in_counter + 1;
        end
    end

always@(posedge clk or negedge rst_n)
    begin
       if(~rst_n)
        begin
           vertex_count <= 0;
           tile_count <= 0;
           test_end <= 0; 
        end
       else if(bte_start)
        begin
            if(vertex_count == 32'd511 && tile_count == 32'd4095)
            begin
                vertex_count <= 0;
                tile_count <= 0;
                test_end <= 1; 
            end     
            else if(vertex_count == 32'd511)
                begin
                   tile_count <= tile_count + 1;
                   vertex_count <= 0;
                end
            else
                begin
                   vertex_count <= vertex_count + 1'b1;
                end  
        end
    end

always@(posedge clk or negedge rst_n)
    begin
       if(~rst_n)
            begin
                bte_start <= 0;
                tile_x    <= 0;
                tile_y    <= 0;                         
                vertex0_x <= 48'h0;              
                vertex0_y <= 48'h0;              
                vertex1_x <= 48'h0;              
                vertex1_y <= 48'h0;                
                vertex2_x <= 48'h0;              
                vertex2_y <= 48'h0;                
            end
        else if(~bte_busy && ~test_end && ~bte_start)
            begin
                bte_start <= 1;
                `ifdef TEST_FIRST
                     {vertex2_y,vertex2_x,vertex1_y,vertex1_x,vertex0_y,vertex0_x} <= vertex_buffer[132];
                     tile_y <= 0; 
                     tile_x <= 32'h700000; 
                `else
                {vertex2_y,vertex2_x,vertex1_y,vertex1_x,vertex0_y,vertex0_x} <= vertex_buffer[vertex_count];
                if(vertex_count == 32'd511)
                begin
                if(tile_x == 32'h3f00000 && tile_y == 32'h3f00000)
                    begin
                       tile_y <= 0; 
                       tile_x <= 0; 
                    end                
                else if(tile_x == 32'h3f00000)
                    begin
                       tile_y <= tile_y + 32'h100000; 
                       tile_x <= 0; 
                    end
                else 
                    begin
                        tile_x <= tile_x + 32'h100000;
                    end
                end
                `endif
            end
        else
            begin
                bte_start <= 0;
            end
    end

always@(posedge clk or negedge rst_n)
    begin
        if(~rst_n)
            busy <= 0;
        else
            busy <= $urandom_range(1'b0,1'b1);
    end



integer i;
integer j;
integer k;
integer m;
integer n;   
integer pixel_count;
//initial tile coordinate,rang from 0 - 1024, 16 pixel align
initial
begin
   for(m=0;m<64;m=m+1)
   begin
        tile_cor_buffer[m][31:0] = {$urandom_range(12'h0,12'h40),20'b0} ;
        tile_cor_buffer[m][63:32] = {$urandom_range(12'h0,12'h40),20'b0} ; 
        end
end

//
initial
begin
  for(n=0;n<1024;n=n+1)
  begin
        v0x= {$urandom_range(48'h0,48'h4000000)};//48'hffffffffffff)}; 
        v0y= {$urandom_range(48'h0,48'h4000000)};//48'hffffffffffff)};
        v1x= {$urandom_range(48'h0,48'h4000000)};//48'hffffffffffff)}; 
        v1y= {$urandom_range(48'h0,48'h4000000)};//48'hffffffffffff)}; 
        v2x= {$urandom_range(48'h0,48'h4000000)};//48'hffffffffffff)}; 
        v2y= {$urandom_range(48'h0,48'h4000000)};//48'hffffffffffff)};
        area = (v1x - v0x) * (v2y - v0y) + (v2x - v0x) * (v1y - v0y);
        if(area > 0)
           vertex_buffer[n] = {v2y,v2x,v1y,v1x,v0y,v0x};
        else
           vertex_buffer[n] = {v1y,v1x,v2y,v2x,v0y,v0x}; 
  end
end

wire [63:0] test_data0 =  $signed( a0) *$signed( cur_tile_x); 
wire [63:0] test_data1 =    $signed(b0) * $signed(cur_tile_y); 
wire [63:0] test_data2 =    $signed(x0) * $signed(y1);
wire [63:0] test_data3 =    $signed(x1) * $signed(y0);

logic [31:0] first_x;
logic [31:0] first_y;

logic [31:0] first_tile;
logic [31:0] first_vertex;

initial
begin
    pixel_count = 0;
    `ifdef TEST_FIRST
       cur_tile_x = (7%64)*16*65536;
       cur_tile_y = (7/64)*16*65536;
         //for(j=0;j<511;j=j+1)
            begin
                {y2,x2,y1,x1,y0,x0} = vertex_buffer[132];
	            a0 = y0- y1;
	            b0 = x1- x0;
	            a1 = y1- y2;
	            b1 = x2- x1;
	            a2 = y2- y0;
	            b2 = x0- x2;
	            ee0_int =$signed(a0) *$signed(cur_tile_x) + $signed(b0) * $signed(cur_tile_y) + $signed(x0) * $signed(y1) - $signed(x1) * $signed(y0);
	            ee1_int =$signed(a1) *$signed(cur_tile_x) + $signed(b1) * $signed(cur_tile_y) + $signed(x1) * $signed(y2) - $signed(x2) * $signed(y1);
	            ee2_int =$signed(a2) *$signed(cur_tile_x) + $signed(b2) * $signed(cur_tile_y) + $signed(x2) * $signed(y0) - $signed(x0) * $signed(y2); 

                judge_t0 = (~a0[31] ) | ( (a0 == 0) & (b0 > 0) );
	            judge_t1 = (~a1[31] ) | ( (a1 == 0) & (b1 > 0) );
                judge_t2 = (~a2[31] ) | ( (a2 == 0) & (b2 > 0) );

                for(k=0;k<256;k=k+1)
                    begin
                        x_temp= k%2 + ((k & 4)>>2)*2 + ((k & 16)>>4)*4 + ((k & 64)>>6)*8 ;
		                y_temp=((k & 2)>>1) + ((k & 8)>>3)*2 + ((k & 32)>>5)*4 + ((k & 128)>>7)*8 ;
	                    cur_ee0 = $signed(ee0_int) +$signed(a0) *$signed(x_temp*65536 + 65536/2) +$signed( b0) * $signed(y_temp*65536 + 65536/2);
		                cur_ee1 = $signed(ee1_int) +$signed(a1) *$signed(x_temp*65536 + 65536/2) +$signed( b1) * $signed(y_temp*65536 + 65536/2);
		                cur_ee2 = $signed(ee2_int) +$signed(a2) *$signed(x_temp*65536 + 65536/2) +$signed( b2) * $signed(y_temp*65536 + 65536/2);
                        if((~cur_ee0[63] || (judge_t0 && cur_ee0 == 0)) & (~cur_ee1[63] || (judge_t1 && cur_ee1 == 0)) & (~cur_ee2[63] || (judge_t2 && cur_ee2 == 0)))
                            begin
                                cur_x = cur_tile_x + x_temp* 65536;
                                cur_y = cur_tile_y + y_temp* 65536;
                                pixel_buffer[pixel_count] = {cur_ee2,cur_ee1,cur_ee0,cur_y,cur_x};
                                if(pixel_count == 0)
                                begin
                                  first_x = cur_x;
                                  first_y = cur_y;
                                  first_tile = i;
                                  first_vertex = j ;
                                end
                                pixel_count = pixel_count + 1;
                            end
                    end
            end  
    `else
   for(i=0;i<4096;i=i+1)
    begin

       cur_tile_x = (i%64)*16*65536;
       cur_tile_y = (i/64)*16*65536;
         for(j=0;j<511;j=j+1)
            begin
                {y2,x2,y1,x1,y0,x0} = vertex_buffer[j];
	            a0 = y0- y1;
	            b0 = x1- x0;
	            a1 = y1- y2;
	            b1 = x2- x1;
	            a2 = y2- y0;
	            b2 = x0- x2;
	            ee0_int =$signed(a0) *$signed(cur_tile_x) + $signed(b0) * $signed(cur_tile_y) + $signed(x0) * $signed(y1) - $signed(x1) * $signed(y0);
	            ee1_int =$signed(a1) *$signed(cur_tile_x) + $signed(b1) * $signed(cur_tile_y) + $signed(x1) * $signed(y2) - $signed(x2) * $signed(y1);
	            ee2_int =$signed(a2) *$signed(cur_tile_x) + $signed(b2) * $signed(cur_tile_y) + $signed(x2) * $signed(y0) - $signed(x0) * $signed(y2); 

                judge_t0 = (~a0[31] ) | ( (a0 == 0) & (b0 > 0) );
	            judge_t1 = (~a1[31] ) | ( (a1 == 0) & (b1 > 0) );
                judge_t2 = (~a2[31] ) | ( (a2 == 0) & (b2 > 0) );

                for(k=0;k<256;k=k+1)
                    begin
                        x_temp= k%2 + ((k & 4)>>2)*2 + ((k & 16)>>4)*4 + ((k & 64)>>6)*8 ;
		                y_temp=((k & 2)>>1) + ((k & 8)>>3)*2 + ((k & 32)>>5)*4 + ((k & 128)>>7)*8 ;
	                    cur_ee0 = $signed(ee0_int) +$signed(a0) *$signed(x_temp*65536 + 65536/2) +$signed( b0) * $signed(y_temp*65536 + 65536/2);
		                cur_ee1 = $signed(ee1_int) +$signed(a1) *$signed(x_temp*65536 + 65536/2) +$signed( b1) * $signed(y_temp*65536 + 65536/2);
		                cur_ee2 = $signed(ee2_int) +$signed(a2) *$signed(x_temp*65536 + 65536/2) +$signed( b2) * $signed(y_temp*65536 + 65536/2);
                        if((~cur_ee0[95] || (judge_t0 && cur_ee0 == 0)) & (~cur_ee1[95] || (judge_t1 && cur_ee1 == 0)) & (~cur_ee2[95] || (judge_t2 && cur_ee2 == 0)))
                            begin
                                cur_x = cur_tile_x + x_temp* 65536;
                                cur_y = cur_tile_y + y_temp* 65536;
                                pixel_buffer[pixel_count] = {cur_ee2,cur_ee1,cur_ee0,cur_y,cur_x};
                                if(pixel_count == 0)
                                begin
                                  first_x = cur_x;
                                  first_y = cur_y;
                                  first_tile = i;
                                  first_vertex = j ;
                                end
                                if(cur_x == 32'h1a00000 && cur_y == 32'h1f0000)
                                begin
                                   first_vertex = j;
                                end
                                pixel_count = pixel_count + 1;
                            end
                    end
            end
    end
    `endif
end

wire [255:0] test_buffer = tile_cor_buffer[0];

endmodule

